package cn.edu.hstc.wm.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;
import cn.edu.hstc.wm.AppConfigs;
import cn.edu.hstc.wm.R;
import cn.edu.hstc.wm.https.HttpUtils;

/**
 * @ClassName: UpdateManager
 * @Description: 更新管理
 * @ModificationHistory
 */
public class UpdateManager {

	public static final String APP_VERSION = "version";
	public static final String APP_NAME = "name";
	public static final String APP_URL = "url";

	/** 下载状态--下载中 */
	private static final int DOWNLOAD_ING = 1;
	/** 下载状态--下载成功 */
	private static final int DOWNLOAD_SUCCESS = 2;
	/** 下载状态--下载失败 */
	private static final int DOWNLOAD_FAIL = 3;

	private Context mContext;

	/** 检查更新时的提示 */
	private ProgressDialog mCheckProgressDialog;
	/** 下载更新进度条 */
	private ProgressBar mUpdateProgressBar;
	/** 记录进度条数值 */
	private int mCurRate;
	/** 保存解析的XML信息 */
	private HashMap<String, String> mHashMap;

	/** 是否取消更新 */
	private boolean cancelUpdate = false;
	/** 是否正在下载更新 */
	private boolean downLoading = false;

	/** 下载保存路径 */
	private String mSavePath;
	/** 下载对话框 */
	private Dialog mDownloadDialog;

	private Handler mHandler;

	private static UpdateManager sManager = null;

	public static UpdateManager getUpdateManager(Context context) {
		if (null == sManager) {
			sManager = new UpdateManager(context);
		}
		return sManager;
	}

	/**
	 * 更新管理器,调用checkUpdate来更新
	 * 
	 * @param context
	 */
	private UpdateManager(Context context) {
		this.mContext = context;
		mHandler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case DOWNLOAD_ING:
					// 更新进度条
					mUpdateProgressBar.setProgress(mCurRate);
					break;
				case DOWNLOAD_SUCCESS:
					// 安装APK
					installApk();
					break;
				case DOWNLOAD_FAIL:
					Toast.makeText(mContext, "文件下载失败！", Toast.LENGTH_SHORT).show();
					break;
				}
			}

		};
		initCheckProgrssDialog();
	}

	/**
	 * 正在检查更新
	 */
	private void initCheckProgrssDialog() {
		if (mCheckProgressDialog == null) {
			mCheckProgressDialog = ProgressDialog.show(mContext, null, "正在检测，请稍后...", true, true);
		} else {
			return;
		}
	}

	/**
	 * 检测软件更新
	 * 
	 * @param isAuto
	 *            为true:软件自动检测更新；false：用户手动检测更新。
	 */
	public void checkUpdate(boolean isAuto) {
		// 如果正在下载则显示下载界面
		if (downLoading) {
			mDownloadDialog.show();
			return;
		}
		if (isAuto) {
			// 启动检查
			new CheckTask().execute(AppConfigs.APP_UPDATE_URL);
		} else if (!isAuto) {
			// 告诉用户已是最新版本，不需要更新。
			Toast.makeText(mContext, "您的软件已是最新版本，不需要更新！", Toast.LENGTH_SHORT).show();
		}

	}

	/**
	 * 获取软件当前版本号
	 * 
	 * @param context
	 * @return
	 */
	private int getVersionVode(Context context) {
		int versionCode = 0;
		// 获取软件版本号，对应AndroidManifest.xml下android:versionCode
		try {
			versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return versionCode;
	}

	/**
	 * 显示软件更新对话框
	 */
	private void showNoticeDialog() {
		AlertDialog.Builder builder = new Builder(mContext);
		builder.setTitle("软件更新").setMessage("软件有新版本，要更新吗？").setPositiveButton("立即更新", new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
				// 显示软件下载对话框
				showDownloadDialog();
			}
		}).setNegativeButton("稍后再说", new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		}).create().show();
	}

	/**
	 * 显示软件下载对话框
	 */
	private void showDownloadDialog() {
		AlertDialog.Builder builder = new Builder(mContext);
		builder.setTitle("正在更新");
		// 给对话框增加进度条
		LayoutInflater inflater = LayoutInflater.from(mContext);
		View v = inflater.inflate(R.layout.update_progress, null);
		mUpdateProgressBar = (ProgressBar) v.findViewById(R.id.update_progressBar);

		mDownloadDialog = builder.setView(v).setPositiveButton("后台更新", new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				// 后台更新
				dialog.dismiss();
			}
		}).setNegativeButton("取消更新", new OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
				// 设置取消状态
				cancelUpdate = true;
			}
		}).create();
		mDownloadDialog.show();
		// 下载APK文件
		downloadApk();
	}

	/**
	 * 下载APK文件
	 */
	private void downloadApk() {
		downLoading = true;
		// 启动下载APK线程
		new DownloadApkThread().start();
	}

	/**
	 * 下载APK文件线程
	 */
	private class DownloadApkThread extends Thread {

		@Override
		public void run() {
			FileOutputStream fos = null;
			// 判断SD卡是否存在，并且是否有读写权限
			if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
				// 获取SD卡路径
				String sdPadth = Environment.getExternalStorageDirectory() + "";
				mSavePath = sdPadth + "/download";
				downLoad(fos);

			} else {
				Toast.makeText(mContext, "SD卡不可访问", Toast.LENGTH_SHORT).show();
				mHandler.sendEmptyMessage(DOWNLOAD_FAIL);
			}
		}
	}

	private void downLoad(FileOutputStream fos) {
		try {
			URL url = new URL(mHashMap.get(APP_URL));
			// 创建连接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(AppConfigs.HTTP_TIMEOUT);
			conn.connect();
			// 获取文件大小
			int fileSize = conn.getContentLength();
			// 创建输入流
			InputStream inStream = conn.getInputStream();
			// 创建文件路径
			File file = new File(mSavePath);
			// 判断文件目录是否存在,不存在则创建该目录
			if (!file.exists()) {
				file.mkdir();
			}
			// 创建文件
			File apkFile = new File(mSavePath, mHashMap.get(APP_NAME));
			fos = new FileOutputStream(apkFile);

			// 当前已下载文件的大小
			int curDownLoadSize = 0;
			// 缓存
			byte[] b = new byte[1024];

			// 循环读取数据流,直到取消或者下载完成
			do {
				int numRead = inStream.read(b);
				curDownLoadSize += numRead;
				// 计算进度条位置
				mCurRate = (int) (((float) curDownLoadSize / fileSize) * 100);
				// 更新进度
				mHandler.sendEmptyMessage(DOWNLOAD_ING);
				// 下载完成
				if (numRead <= 0) {
					mHandler.sendEmptyMessage(DOWNLOAD_SUCCESS);
					break;
				}
				// 写入文件
				fos.write(b, 0, numRead);

			} while (!cancelUpdate);

		} catch (Exception e) {
			e.printStackTrace();
			mHandler.sendEmptyMessage(DOWNLOAD_FAIL);
		} finally {
			// 没有正在下载更新
			downLoading = false;
			mDownloadDialog.dismiss();
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * 安装APK
	 */
	private void installApk() {
		// 没有调用将导致内存泄漏
		mDownloadDialog.dismiss();

		File apk = new File(mSavePath, mHashMap.get("name"));
		if (!apk.exists()) {
			Toast.makeText(mContext, "找不到文件!", Toast.LENGTH_SHORT).show();
			return;
		}
		// 通过Intent安装APK文件
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.parse("file://" + apk.toString()), "application/vnd.android.package-archive");
		mContext.startActivity(intent);
	}

	private final class CheckTask extends AsyncTask<String, Integer, Boolean> {

		@Override
		protected Boolean doInBackground(String... params) {
			Log.d("CheckTask", "doInBackground");
			// 获取当前软件版本
			int versionCode = getVersionVode(mContext);

			try {
				InputStream inStream = HttpUtils.getInputStream(params[0], null, HttpUtils.METHOD_GET);
				// 解析xml文件。
				try {
					mHashMap = ParseXmlService.parseXml(inStream);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					inStream.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}

			try {
				// 获得数据
				if (null != mHashMap) {
					int serviceCode = Integer.valueOf(mHashMap.get(APP_VERSION));
					// 判断版本号
					if (serviceCode > versionCode) {
						return true;
					}
				}
			} catch (NumberFormatException e) {
				e.printStackTrace();
				return false;
			}

			return false;
		}

		@Override
		protected void onPreExecute() {
			Log.d("CheckTask", "onPreExecute");
			// 显示正在检查
			mCheckProgressDialog.show();
		}

		@Override
		protected void onPostExecute(Boolean result) {
			// 消失...
			mCheckProgressDialog.dismiss();
			// 检查结束,返回检查结果
			if (result) {
				// 显示提示有更新的对话框
				showNoticeDialog();
			} else {
				// 告诉用户已是最新版本，不需要更新。
				Toast.makeText(mContext, "您的软件已是最新版本，不需要更新！", Toast.LENGTH_SHORT).show();
			}
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
		}

		@TargetApi(Build.VERSION_CODES.HONEYCOMB)
		@Override
		protected void onCancelled(Boolean result) {
			// TODO Auto-generated method stub
			super.onCancelled(result);
		}

		@Override
		protected void onCancelled() {
			// TODO Auto-generated method stub
			super.onCancelled();
		}

	}
}
